/*************************************************
Name : QuickAppRequest_WS
Created By : dthekumparampil
Created Date : Jan 9, 2013
Description : An Apex REST service class created to recieve the incoming request from WIU QuickApp for lead conversion or Account update.
*******************************
Modified By : dthekumparampil
Modified Date : Jan 16, 2013
Modification : 	Implementing the logic, where the ID recieved is checked against Account and lead, opportunity is created and Account id returned

******************************
Modified By : dthekumparampil
Modified Date : Feb 21, 2013 
Modification :  Passing additional parameter caseOrigin when calling method newOpportunityForAccount().
				Modified the account and lead search to use colleague ID rather that Salesforce ID.

*************************************************/

@RestResource(urlMapping='/QuickAppRequest/*')
global with sharing class QuickAppRequest_WS {
    
/**
Method Name : convertLeadOrUpdateAccount 
Created By : dthekumparampil
Created Date : Jan 9, 2013 
Description : Its just a dummy method which accepts the inputs and returns a dummy accountid.
Input Parameters : String FirstName,String LastName,String EmailAddress,String State,String ProgramOfInterest,String StartTerm,String Status,String SubStatus,String SalesforceID,String Phone
Output Parameters : String newAccountId
**************************************
Modified By : dthekumparampil
Modified Date : Jan 16, 2013
Modification :  Implementing the logic, where the ID recieved is checked against Account, 
				if found, an opportunity is created with the given data and the account status is updated.
				If not found in Account, its checked in Lead, if found, convert lead to account, add opportunity & update account status.
				If not found in Lead or Account, return Failure: no match in salesforce.
				
**************************************
Modified By : dthekumparampil
Modified Date : Jan 28, 2013
Modification :	Removed sub-status from mandatory input field check.
				Account status will not be changed. 
				The converted Lead status is set as 'Application Started'.
				Phone number is formatted to (XXX) XXX-XXXX.
**/    
    
    @HttpPost
    global static String convertLeadOrUpdateAccount(String FirstName,String LastName,
    String EmailAddress,String State,String ProgramOfInterest,String StartTerm,
    String Status,String SubStatus,String SalesforceID,String Phone) {
    String strInputParameters = '';	
    	/*Trimming all the Input strings*/
        FirstName=FirstName.trim();
        strInputParameters +=' FirstName: '+FirstName+' ';
        LastName=LastName.trim();
        strInputParameters +=' LastName: '+LastName+' ';
        EmailAddress=EmailAddress.trim();
        strInputParameters +=' EmailAddress: '+EmailAddress+' ';
        State=State.trim();
        strInputParameters +=' State: '+State+' ';
        ProgramOfInterest=ProgramOfInterest.trim();
        strInputParameters +=' ProgramOfInterest: '+ProgramOfInterest+' ';
        StartTerm=StartTerm.trim();
        strInputParameters +=' StartTerm: '+StartTerm+' ';
        Status= Status.trim();
        strInputParameters +=' Status: '+Status+' ';
        SubStatus = SubStatus.trim();
        strInputParameters +=' SubStatus: '+SubStatus+' ';
        SalesforceID = SalesforceID.trim();
        strInputParameters +=' SalesforceID: '+SalesforceID+' ';
        Phone=Phone.trim();
        strInputParameters +=' Phone: '+Phone+' ';
        
        /*Getting RecordType IDs*/
        String accountRecordType = Schema.Sobjecttype.Account.getRecordTypeInfosByName().get('West - Student Account').getRecordTypeId();
        String leadRecordType = Schema.Sobjecttype.Lead.getRecordTypeInfosByName().get('West - Prospective Student').getRecordTypeId();
        String opportunityRecordType = Schema.Sobjecttype.Opportunity.getRecordTypeInfosByName().get('West - Student Application').getRecordTypeId();
        String programRecordType = Schema.Sobjecttype.Program__c.getRecordTypeInfosByName().get('West - Program').getRecordTypeId();

        /*Checking for empty strings in required fields.*/
        if(FirstName==''|| LastName==''|| EmailAddress==''|| State==''|| ProgramOfInterest==''|| StartTerm=='' || Status == ''  ||SalesforceID==''){
        	return 'Failure: FirstName, LastName, EmailAddress, State, ProgramOfInterest, StartTerm, Status, SubStatus and SalesforceID are mandatory fields';
        }
        
        /*Formatting Phone number*/
        if(Phone.length()>0){
	        DataFormatter formatter = new DataFormatter();
	        Phone = formatter.phoneFormatter(Phone);
	        if(Phone.contains('Failed')){
	        	system.debug('Phone format error: '+Phone);
	        	return 'Failure: Please enter a valid phone number';
	        }
        }
        
        /*Checking if Date formatting is matching with Salesforce*/
	    try{
	       	/*Date we get is in the format MM/YYYY, which is converted to YYYY-MM-DD for salesforce*/
	        String[] splitDate = StartTerm.split('/', 0);
	        StartTerm = splitDate[1].trim()+'-'+splitDate[0].trim()+'-01';/*trimming is done for individual date strings*/
		}
        catch (Exception e){
	        return 'Failure: Date Format not supported.';
	    }
	    
	    /*Checking if Program Name exists in Database.*/
        Program__c programValue;
        try{
        	system.debug(ProgramOfInterest );
            programValue = [select id, name from Program__C where name =: ProgramOfInterest AND RecordTypeId=:programRecordType AND Active__c =: true LIMIT 1];
        }
        catch (Queryexception qE){
            System.debug('Error with Program Name '+qE.getMessage());
            return 'Failure: No matching Program Of Interest in Database.';
        }
        
        /****
        In the below code, first the salesforceID is searched in account, if found, a new Opportunity is created for this
        account, the values are inserted in the fields and the Account id is returned.
        If no Account record found, duplicate in Lead is searched, if found, its converted to PersonAccount,
        a new Opportunity is created for it, the values are inserted in the fields, existing cases are transfered and the Account id is returned.
        If no record found in Lead or Account, we return failure message.
        Duplicate matching is based on FirstName, LastName and EmailAddress.
        ****/
        
        /*Checking Salesforce Id in Account*/
        list<Account> accountInSalesforce;
    	accountInSalesforce = [select id, FirstName, LastName, Phone, PersonEmail, Personal_Email__pc, Status__c, Account_Id__C from Account 
    	where IsPersonAccount=true AND Account_Id__C=:SalesforceID AND RecordTypeId =: accountRecordType];
        
        /****If found, update existing Account record, create new Opportunity with given data and return account id.
        New Opportunity is created only if the status of existing opportunities of the Account is either
        'Started' or 'Graduated' or 'Dropped' or 'Exited' or 'Declined' or 'No further Action'. Else a Case is created. 
        This logic is implemented in WebServicesUtil Class****/
        if(accountInSalesforce.size()>0){
        	accountInSalesforce[0].FirstName = FirstName;
        	accountInSalesforce[0].LastName = LastName;
        	accountInSalesforce[0].Personal_Email__pc = EmailAddress;
        	accountInSalesforce[0].BillingState = State;
        	accountInSalesforce[0].BillingCountry = 'USA';
        	//accountInSalesforce[0].Status__c = 'Prospect';
        	
    		if(Phone.length()>0)
    			accountInSalesforce[0].PersonHomePhone=Phone; // need to check if this works.. 
        	
        	/*Set Savepoint for rollback in case the opportunity cannot be created or attached.*/
        	Savepoint savepoint1 = Database.setSavepoint();
        	
        	try{
        		update accountInSalesforce[0]; 
        	}
        	catch(DmlException de){
        		Database.rollback(savepoint1);
        		System.debug('Account insertion error: '+de.getmessage());
        		GeneralUtilWCM.createErrorLog('QuickAppRequest_WS',strInputParameters,'Failure: Unable to modify Account '+de.getmessage(),false);
        		return 'Failure: Unable to modify Account';
        	}
        	
        	/****Calling Helper class containing new opprotunity creation method****/
        	WebServicesUtil utility = new WebServicesUtil();
        	
        	Boolean opportunityCreationIsSuccess = utility.newOpportunityForAccount(accountInSalesforce[0].id, programValue.id,
        	opportunityRecordType, LastName+' - '+programValue.name, Status, SubStatus, StartTerm, 'QuickApp');
        	
        	if(!opportunityCreationIsSuccess){
        		Database.rollback(savepoint1);
        		GeneralUtilWCM.createErrorLog('QuickAppRequest_WS',strInputParameters,'Failure: Unable to create new Opportunity. Look for error log from WebServicesUtil for more details.',false);
        		return 'Failure: Unable to create new Opportunity';
        	}
        	//Commented by Shyam Kannapiran based on new change request from Penny Havely.
		    //return 'Success: '+accountInSalesforce[0].Account_Id__C;
		    return 'Success: '+true;
		}
		/*Checking in Lead for matching id*/
		else{
			list<Lead> leadInSalesforce;
			
        	leadInSalesforce = [select id, FirstName, LastName, state, program__c, recordTypeID, Country, Home_phone__c, phone, Personal_Email__c, 
        	Email, Marketing_Email__c, Other_Email_2__c, Other_Email__c, Preferred_Email__c, IsConverted,
        	University_Email__c, work_Email__c, Lead_Id__C from lead where Lead_Id__C=:SalesforceID AND recordTypeID=:leadRecordType AND IsConverted=:false];

	        /*If Found, Convert Lead into PersonAccount and move the cases to the personAccount*/
	        if(leadInSalesforce.size()>0){
	        	
	        	/****Getting the cases for that lead ****/
	        	list<Case> leadCases = [select id,AccountId,Lead__c from Case where Lead__c=:leadInSalesforce[0].id];
	        	
	        	/****Set Savepoint for rollback ****/
	        	Savepoint savepointForLeadConversion = Database.setSavepoint();
	        	
	        	/****Updating the Lead****/
	        	leadInSalesforce[0].State = State;
	        	leadInSalesforce[0].Program__c = programValue.Id;
	        	leadInSalesforce[0].Country = 'USA';
	        	leadInSalesforce[0].Personal_Email__c = EmailAddress;
	        	if(Phone.length()>0){
        			leadInSalesforce[0].Home_Phone__c = Phone;
        		}
        		try{
	        		leadInSalesforce[0].Anticipated_Start_Date__c = Date.valueOf(StartTerm);
	        	}
	        	catch(Exception e){
		            return 'Failure: Date Format not supported.';
	        	}
				try{
	        		update leadInSalesforce[0];
	        	}
	        	catch(DmlException de){
	        		GeneralUtilWCM.createErrorLog('QuickAppRequest_WS',strInputParameters,'Failure: Lead already exists in database, but unable to update '+de.getmessage(),false);
	        		return 'Failure: Lead already exists in database, but unable to update';
	        	}
	        	
	        	System.Debug('Before Lead Convert>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\nID: '+leadInSalesforce[0].id);
        		
	        	/****Performing Lead Convert****/
	        	Database.Leadconvert leadToConvert = new Database.Leadconvert();
	        	leadToConvert.setLeadId(leadInSalesforce[0].id);
	        	//leadToConvert.setOwnerId('005L0000000GHLWIA4');
	        	LeadStatus convertStatus = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1];//AND MasterLabel='Application Started'
	        	
	        	System.Debug('Before Lead Convert>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\nLeadStatus ID: '+convertStatus.id+'\nMasterLabel: '+convertStatus.MasterLabel);
	        	leadToConvert.setConvertedStatus(convertStatus.MasterLabel);
	        	Database.Leadconvertresult convertResult;

        		convertResult = Database.convertLead(leadToConvert, true);

	        	String convertedAccountID = convertResult.getAccountId();
	        	if(convertedAccountID=='' ||convertedAccountID==null){
	        		Database.rollback(savepointForLeadConversion);
	        		return 'Failure: Problem with conversion';
	        	}
	        	
	        	system.debug('after conversion : '+convertedAccountID+'\nbefore updating account fields');
	        	
	        	/****Updating Account Fields****/
	        	Account convertedAccount = [select id, Personal_Email__pc,PersonHomePhone, Account_Id__C from Account where id=:convertedAccountID LIMIT 1];
	        	convertedAccount.Personal_Email__pc= EmailAddress;
	        	convertedAccount.PersonHomePhone = Phone;
	        	update convertedAccount;
	        	
	        	/****Passing the lead Cases to the newly created account ****/
	        	if(leadCases.size()>0){
	        		for(Integer index=0;index<leadCases.size();index++){
	        			leadCases[index].AccountId=convertResult.getAccountId();
	        			leadCases[index].lead__C = null;
	        		}
	        		try{
	        			update leadCases;
	        		}
	        		catch(DmlException de){
	        			Database.rollback(savepointForLeadConversion);
	        			system.debug('Problem with updating the Cases : '+de.getMessage());
	        			GeneralUtilWCM.createErrorLog('QuickAppRequest_WS',strInputParameters,'Problem with updating the Cases : '+de.getMessage(),false);
	        			return 'Failure: Unable to transfer Cases to new Account';
	        		}
	        	}
	        	//Commented by Shyam Kannapiran based on new change request from Penny Havely. 
	        	//return 'Success: '+convertedAccount.Account_Id__C;
	        	return 'Success: '+true;	
	        }
	        else{
	        	GeneralUtilWCM.createErrorLog('QuickAppRequest_WS',strInputParameters,'Failure: SalesforceID not found',false);
	        	return 'Failure: SalesforceID not found';
	        }	
		}
    }
}